import pathlib
import re
import logging
from typing import List, Pattern

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
logger = logging.getLogger(__name__)

def find_python_files(root_dir: pathlib.Path, exclude_patterns: List[Pattern[str]]) -> List[pathlib.Path]:
    """
    Recursively finds all Python files (*.py) within the root directory,
    excluding paths that match any of the provided regex patterns.

    Args:
        root_dir: The absolute path to the project's root directory.
        exclude_patterns: A list of compiled regular expression patterns to exclude.

    Returns:
        A list of absolute pathlib.Path objects for the discovered Python files.
    """
    if not root_dir.is_dir():
        logger.error(f"Root directory not found or is not a directory: {root_dir}")
        return []

    discovered_files: List[pathlib.Path] = []
    logger.info(f"Starting file discovery in: {root_dir}")
    # Use try-except around rglob if permission errors are possible
    try:
        all_py_files = list(root_dir.rglob('*.py')) # Collect all first
    except PermissionError as e:
        logger.error(f"Permission error scanning directory: {e}")
        return []
    except Exception as e:
        logger.error(f"Error during file scanning: {e}", exc_info=True)
        return []

    logger.info(f"Found {len(all_py_files)} total '.py' files initially.")

    excluded_count = 0
    for py_file in all_py_files:
        # Resolve symlinks and make absolute *before* pattern matching
        try:
            abs_path = py_file.resolve()
        except OSError as e: # Handle potential errors during resolve (e.g., broken symlink)
            logger.warning(f"Could not resolve path: {py_file}. Error: {e}. Skipping.")
            excluded_count += 1
            continue

        # Use POSIX-style paths for consistent regex matching across OS
        path_str = abs_path.as_posix()
        is_excluded = False
        matched_pattern = None
        for pattern in exclude_patterns:
            # Use search to find pattern anywhere in the path string
            if pattern.search(path_str):
                #logger.debug(f"Excluding '{abs_path}' due to pattern: {pattern.pattern}")
                is_excluded = True
                matched_pattern = pattern.pattern
                break

        if not is_excluded:
            discovered_files.append(abs_path)
            # logger.debug(f"Including file: '{abs_path}'")
        else:
            excluded_count += 1
            logger.debug(f"Excluding '{abs_path}' due to pattern: {matched_pattern}")

    logger.info(f"Found {len(discovered_files)} Python files in '{root_dir}' after excluding {excluded_count} files.")
    # Log first few found files for verification if debugging needed
    if discovered_files and logger.isEnabledFor(logging.DEBUG):
        log_limit = 5
        logger.debug(f"First {min(len(discovered_files), log_limit)} included files:")
        for i, f in enumerate(discovered_files[:log_limit]):
            try:
                logger.debug(f"  - {f.relative_to(root_dir)}")
            except ValueError:
                logger.debug(f"  - {f} (outside relative root?)")

    return discovered_files